package com.hjm.friend.service.user.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hjm.common.core.constants.SecurityConstants;
import com.hjm.common.core.domain.page.TableDataInfo;
import com.hjm.common.core.enums.ExamType;
import com.hjm.common.core.enums.ResultCode;
import com.hjm.common.core.utils.ThreadLocalUtils;
import com.hjm.friend.domain.exam.Exam;
import com.hjm.friend.domain.exam.dto.ExamQueryDTO;
import com.hjm.friend.domain.exam.vo.ExamVO;
import com.hjm.friend.domain.user.UserExam;
import com.hjm.friend.domain.user.dto.UserExamDTO;
import com.hjm.friend.manage.ExamCacheManager;
import com.hjm.friend.mapper.exam.ExamMapper;
import com.hjm.friend.mapper.user.UserExamMapper;
import com.hjm.friend.service.user.UserExamService;
import com.hjm.security.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


@Service
public class UserExamServiceImpl implements UserExamService {

    @Autowired
    private UserExamMapper userExamMapper;

    @Autowired
    private ExamCacheManager examCacheManager;

    @Autowired
    private ExamMapper examMapper;


    @Override
    public int enter(UserExamDTO userExamDTO) {
        // 获取 用户 userId

        Long userId =ThreadLocalUtils.get(SecurityConstants.USER_ID, Long.class);

        // 对 竞赛信息进行校验
        Exam exam = examMapper.selectById(userExamDTO.getExamId());
        if(BeanUtil.isEmpty(exam)) {
            // 竞赛不存在
            throw new ServiceException(ResultCode.EXAM_IS_NOT_EXISTS);
        }
        UserExam userExam = userExamMapper.selectOne(new LambdaQueryWrapper<UserExam>().
                eq(UserExam::getExamId, userExamDTO.getExamId()).
                eq(UserExam::getUserId, userId));
        if(BeanUtil.isNotEmpty(userExam)){
            // 竞赛已报名
            throw new ServiceException(ResultCode.USER_IS_ENTER);
        }

        // 插入我的竞赛信息
        examCacheManager.addUserExamCache(userId,userExamDTO.getExamId());


        // 插入数据库
        userExam = new UserExam();
        userExam.setExamId(userExamDTO.getExamId());
        userExam.setUserId(userId);
        return userExamMapper.insert(userExam);
    }

    @Override
    public TableDataInfo list(ExamQueryDTO examQueryDTO) {
        // 拿到 用户 userId
        Long userId = ThreadLocalUtils.get(SecurityConstants.USER_ID,Long.class);
        // 从redis 中 获取 用户竞赛 数据
        Long total = examCacheManager.getListSize(ExamType.USER_EXAM_LIST.getType(),userId);

        List<ExamVO> examVOList ;

        if(total == null || total <= 0 ){
            PageHelper.startPage(examQueryDTO.getPageNum(),examQueryDTO.getPageSize());
            // 说明 redis 中没有数据，就需要 从数据库中进行同步
            examVOList = userExamMapper.selectUserExamList(userId);

            // 更新 redis 缓存中的 用户竞赛信息
            examCacheManager.refreshCache(ExamType.USER_EXAM_LIST.getType(), userId);

            // 数据从 数据库中同步 过来的， 所以可以直接 使用 page 插件获得的 total
            total = new PageInfo<>(examVOList).getTotal();
        }else{
            // 手动设置 type
            examQueryDTO.setType(ExamType.USER_EXAM_LIST.getType());
            examVOList = examCacheManager.getExamVOList(examQueryDTO,userId);
            total = examCacheManager.getListSize(ExamType.USER_EXAM_LIST.getType(),userId);
        }

        // 此时 examVO 中的数据 与 数据库中的 完全一致

        // 当然我们还需要 将符合条件的 total 进行返回

        return TableDataInfo.success(examVOList,total);
    }
}
